﻿using System.Collections.Generic;
using GalaSoft.MvvmLight.Messaging;
using Moq;
using NUnit.Framework;
using SessionHunter.DataAccess;
using SessionHunter.Messages;
using SessionHunter.Model;
using SessionHunter.UnitTests.Business;
using SessionHunter.Utilities;
using SessionHunter.ViewModel;

namespace SessionHunter.UnitTests.ViewModel
{
    [TestFixture]
    public class TestMainViewModel : TestBase
    {
        private UIHelper uiHelper = new UIHelper(false);

        [Test]
        public void Command_ShowAllSessions_SetTrue_OptionSaved()
        {
            bool called = false;
            // Mock out the method, since we can't access isolated storage from unit tests
            var repo = new Mock<ApplicationRepository>() { CallBase = true };
            repo.Setup(t => t.SaveOption<int>(ApplicationRepository.PersistedSettings.NumberOfSessions, ApplicationOptions.ShowAllSessionsValue)).Callback(() => called = true);

            var vm = new MainViewModel(repo.Object);
            vm.Command_ShowAllSessions.Execute(true);
            Assert.IsTrue(called);
        }

        [Test]
        public void Command_ShowAllSessions_SetFalse_OptionSaved()
        {
            bool called = false;
            // Mock out the method, since we can't access isolated storage from unit tests
            var repo = new Mock<ApplicationRepository>() { CallBase = true };
            repo.Setup(t => t.SaveOption<int>(ApplicationRepository.PersistedSettings.NumberOfSessions, ApplicationOptions.DefaultNumberOfSessions)).Callback(() => called = true);

            var vm = new MainViewModel(repo.Object);
            vm.Command_ShowAllSessions.Execute(false);
            Assert.IsTrue(called);
        }

        [Test]
        public void PopulateSessionList_CorrectSessionItem_ReturnsList()
        {
            // Arrange
            var sessionData = new SessionData("000000", 0);
            sessionData.Data = Helper.StringToByteArray(TestSessionReading.ExternalObjectSessionData);

            var mainViewModel = new Mock<MainViewModel>() { CallBase = true };
            mainViewModel.Setup(mock => mock.RaiseMissingAssembly(It.IsAny<string>()));

            // Act
            var retVal = mainViewModel.Object.PopulateSessionItems(sessionData, uiHelper);

            // Assert
            Assert.NotNull(retVal);
            Assert.AreEqual(2, retVal.Count);
        }

        [Test]
        public void PopulateSessionList_UnresolvedSessionItem_CallReferencesAction()
        {
            // Arrange
            var sessionData = new SessionData("000000", 0);
            sessionData.Data = Helper.StringToByteArray(TestSessionReading.ExternalObjectSessionData);

            var mainViewModel = new Mock<MainViewModel>() { CallBase = true };
            List<SessionItem> list = new List<SessionItem>();
            list.Add(new SessionItem() { Item = sessionData });
            mainViewModel.Setup(mock => mock.GetSessionItems(sessionData, uiHelper, out list)).Returns(false);
            mainViewModel.Setup(mock => mock.RaiseMissingAssembly(It.IsAny<string>()));

            bool wasCalled = false;
            // Make sure we are raising a message to bring attention to the reference button
            Messenger.Default.Register<MainWindowMessage>(this, (msg) => wasCalled = (msg.Message == MainWindowMessage.MessageAction.References_Attention));

            // Act
            var retVal = mainViewModel.Object.PopulateSessionItems(sessionData, uiHelper);
            Messenger.Default.Unregister<MainWindowMessage>(this);

            // Assert
            Assert.IsTrue(wasCalled, "No message was raised for MainWindowMessage");

        }
    }
}
